package com.iogogogo.supervisord4j.base.configuration;

import com.iogogogo.supervisord.properties.SupervisordProperties;
import com.iogogogo.supervisord4j.properties.InstanceProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * Created by tao.zeng on 2021/7/12.
 */
@Slf4j
public class MultiInstanceConfigure implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {

    private ApplicationContext applicationContext;

    private InstanceProperties instanceProperties;

    @Override
    public void setBeanName(@NonNull String beanName) {
        log.info("init beanName: {}", beanName);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Objects.requireNonNull(this.instanceProperties, "instanceProperties is not null.");
        Objects.requireNonNull(this.applicationContext, "applicationContext is not null.");
    }

    /**
     * 动态定义bean
     *
     * @param beanDefinitionRegistry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(@NonNull BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        instanceProperties.getInstance().forEach((k, v) -> {

            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(SupervisordProperties.class, () -> v);

            // 添加属性
            // beanDefinitionBuilder.addPropertyReference("", "");

            AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
            // 设置初始化方法和销毁方法
            beanDefinition.setInitMethodName("init");
            beanDefinition.setDestroyMethodName("destroy");

            beanDefinitionRegistry.registerBeanDefinition(
                    String.join("", k, StringUtils.capitalize(SupervisordProperties.SUPERVISORD_PREFIX)), beanDefinition);
        });
    }

    @Override
    public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void setInstanceProperties(InstanceProperties instanceProperties) {
        this.instanceProperties = instanceProperties;
    }
}
